#include "GameView.h"
#include <OgreConfigFile.h>
#include <OgreViewport.h>
#include <OgreSceneManager.h>
#include "OgreParticleSystemManager.h"
#include <OgreRenderWindow.h>
#include <OgreEntity.h>

//-------------------------------------------------------------------------------------
GameView::GameView(void)
	: mpRoot(0), mpWindow(0), mpSceneMgr(0), mpCamera(0), mpGUI(0), mpVideoSettings(0)
{
}
//-------------------------------------------------------------------------------------
GameView::~GameView(void)
{
	delete mpVideoSettings;
	delete mpGUI;
	delete mpCamera;
	delete mpRoot;
}
//-------------------------------------------------------------------------------------
bool GameView::initView(Ogre::String pluginsFileName,
						Ogre::String configFileName,
						Ogre::String resourcesFileName)
{
    mpRoot = new Ogre::Root(pluginsFileName);

	// Set up resources
	// Load resource paths from config file
	Ogre::ConfigFile cf;
	cf.load(resourcesFileName);

	// Go through all sections & settings in the file
	Ogre::ConfigFile::SectionIterator i = cf.getSectionIterator();
 
	Ogre::String secName, typeName, archName;
	while (i.hasMoreElements())
	{
		secName = i.peekNextKey();
		Ogre::ConfigFile::SettingsMultiMap *settings = i.getNext();
		Ogre::ConfigFile::SettingsMultiMap::iterator j;
		for (j = settings->begin(); j != settings->end(); ++j)
		{
			typeName = j->first;
			archName = j->second;
			Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
				archName, typeName, secName);
		}
	}

	mpVideoSettings = new VideoSettings();

	mpWindow = mpRoot->initialise(true, "Voo");	// globalname!!

	// Set default mipmap level (note: some APIs ignore this)
	Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
	// Initialise all resource groups
	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); // invalidParamException

	// Create the SceneManager, in this case a generic one
	mpSceneMgr = mpRoot->createSceneManager("DefaultSceneManager");

	// Create the camera
	mpCamera = new GameCamera(mpSceneMgr->createCamera("PlayerCam"), mpWindow, 10.0f , 12.0f);

	// Create a skybox
	setSkyBox("Examples/JitterSkyBox");

	// Set ambient light
	mpSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
 
	// Create a light
	Ogre::Light* l = mpSceneMgr->createLight("MainLight");
	l->setPosition(20,80,50);

	// Create GUI
	mpGUI = new GameGUI(mpWindow);
	mpGUI->init(mpVideoSettings);
	
	return true;
}
//-------------------------------------------------------------------------------------
void GameView::setSkyBox(Ogre::String res)
{
	mpSceneMgr->setSkyBox(true, res);
}
//-------------------------------------------------------------------------------------
void GameView::addFrameListener(Ogre::FrameListener *listener)
{
	mpRoot->addFrameListener(listener);
}
//-------------------------------------------------------------------------------------
void GameView::removeFrameListener(Ogre::FrameListener *listener)
{
	mpRoot->removeFrameListener(listener);
}
//-------------------------------------------------------------------------------------
void GameView::startRendering()
{
	mpRoot->startRendering();
}
//-------------------------------------------------------------------------------------
bool GameView::createVisibleObject(const VisibleObjectPtr obj)
{
	OgreDataPtr data = obj->getOgreInitData();

	Ogre::Entity *entity;
	if (mpSceneMgr->hasEntity(*(data->name)))
	{
		mpSceneMgr->destroyEntity(*(data->name));
	}
	entity = mpSceneMgr->createEntity(*(data->name), *(data->meshName));

	Ogre::SceneNode *node = mpSceneMgr->getRootSceneNode()->createChildSceneNode(data->pos);

	node->scale(data->scale);
	node->setOrientation(data->quat);
	node->roll(data->roll);
	node->pitch(data->pitch);
	node->yaw(data->yaw);

	entity->setVisible(obj->getOgreInitData()->visible);

	node->attachObject(entity);

	obj->setEntityNode(node);
	obj->setAnimator(new Animator(obj->getEntity()));

	//configure material
	if(data->name->find("transparent") != string::npos)
	{
		entity->getSubEntity(0)->getMaterial()->setCullingMode(Ogre::CULL_NONE);
		entity->getSubEntity(0)->getMaterial()->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
		entity->getSubEntity(0)->getMaterial()->setDepthWriteEnabled(false);
		entity->getSubEntity(0)->getMaterial()->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
		entity->getSubEntity(0)->getMaterial()->getTechnique(0)->getPass(0)->setShadingMode(Ogre::SO_FLAT);
		entity->getSubEntity(0)->getMaterial()->getTechnique(0)->getPass(0)->setLightingEnabled(false);
	}

	return true;
}
//-------------------------------------------------------------------------------------
void GameView::removeObject(Ogre::SceneNode *node)
{
	node->removeAndDestroyAllChildren();
	mpSceneMgr->getRootSceneNode()->removeAndDestroyChild(node->getName());
}

Ogre::RenderWindow *GameView::getWindow() const
{
	return mpWindow;
}
//-------------------------------------------------------------------------------------
Ogre::SceneManager *GameView::getSceneManager(void) const
{
	return mpSceneMgr;
}
//-------------------------------------------------------------------------------------
GameCamera *GameView::getCamera(void) const
{
	return mpCamera;
}
//-------------------------------------------------------------------------------------
void GameView::update(Ogre::Real elapsedTime)
{
	if (mpGUI) mpGUI->update(elapsedTime);
}